package com.randi.common.utils;

import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author randi
 * @version 2023/10/17
 * @Description redis 工具类
 */
@Component
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public class RedisUtil {

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 失效时间（秒）
     * @return true/false 成功/失败
     */
    public boolean expire(String key, long time) {
        try {
            redisTemplate.expire(key, time, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 失效时间（秒）
     * @return true/false 成功/失败
     */
    public boolean expire(String key, long time, TimeUnit timeUnit) {
        try {
            redisTemplate.expire(key, time, timeUnit);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取过期时间
     *
     * @param key 键
     * @return 失效时间（秒） 0：永久有效
     */
    public Long getExpire(String key) {
        return redisTemplate.getExpire(key);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true/false 存在/不存在
     */
    public boolean hasKey(String key) {
        try {
            return Boolean.TRUE.equals(redisTemplate.hasKey(key));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 查找匹配key
     *
     * @param pattern key
     * @return /
     */
    public List<String> scan(String pattern) {
        ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
        RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
        RedisConnection rc = Objects.requireNonNull(factory).getConnection();
        Cursor<byte[]> cursor = rc.scan(options);
        List<String> result = new ArrayList<>();
        while (cursor.hasNext()) {
            result.add(new String(cursor.next()));
        }
        try {
            RedisConnectionUtils.releaseConnection(rc, factory);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 删除缓存
     *
     * @param key 键
     */
    public void delete(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(Arrays.asList(key));
            }
        }
    }

    /**
     * 获取缓存
     *
     * @param key 键
     */
    public <T> T getCache(final String key) {
        ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
        return valueOperations.get(key);
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Set<String> getCacheKeys(final String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * 缓存存入
     *
     * @param key   键
     * @param value 值
     */
    public <T> void setCache(String key, final T value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 缓存存入
     *
     * @param key   键
     * @param value 值
     * @param time  失效时间（秒） <0：永久有效
     */
    public <T> void setCache(String key, final T value, long time) {
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 缓存存入
     *
     * @param key      键
     * @param value    值
     * @param time     失效时间 <0：永久有效
     * @param timeUnit 时间单位
     */
    public <T> void setCache(String key, T value, long time, TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, time, timeUnit);
    }

    /**
     * 递增
     *
     * @param key   键
     * @param delta 递增数
     * @return long
     */
    public Long increment(String key, long delta) {
        if (delta < 0) {
            delta = 0;
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     *
     * @param key   键
     * @param delta 递减数
     * @return long
     */
    public Long decrement(String key, long delta) {
        if (delta < 0) {
            delta = 0;
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }


}
